import {
  getInstanceValue,
  initWatcher,
  getDataType
} from './utils/index.js'
import {
  Node,
  NodeFilter
} from './utils/enums.js'
// import VNode from './VNode/index.js'
import {
  createVNode
} from './VNode/util.js'
import LveError from './Error/index.js'

/**
 * 模板解析
 * @param {*} parentNode
 * @param {*} comp 组件实例
 */
const parse = (parentNode, comp) => {
  // TreeWalker 遍历对应节点和它们的位置。
  const tree = document.createTreeWalker(parentNode, NodeFilter.SHOW_ALL, {acceptNode(node) { return NodeFilter.FILTER_ACCEPT}})
  let node = tree.currentNode // 当前被遍历的节点
  const root = tree.root
  while(node) { // 节点循环遍历
    replace(node, root, comp)
    node = tree.nextNode() // 指针移动到下一个节点
  }
}
/**
 * 对节点的识别替换
 * @param {*} node 当前节点
 * @param {*} root 祖先节点
 * @param {*} comp 组件实例
 */
const replace = (node, root, comp) => {
  const dataReg = /\{\{(.*?)\}\}/g // 识别 {{}} 内数据
  const lineReg = /\/\/.*|\/\*\*[\s\S]*\*\//g // 匹配单行或多行注释符号
  const nodeType = node.nodeType // dom元素类型
  const nodeName = node.nodeName // dom元素名称
  const nodeValue = node.nodeValue // dom元素值 只在属性节点或文本节点才有值
  const text = node.textContent // 元素值
  const attrs = node.attributes // 属性值，只有元素节点才有值
  // 遇到祖先节点 跳过
  if (node === root) {
    return
  }

  // 匹配 文本节点 换行符也属于此
  if (nodeType === Node.TEXT_NODE) {
    // 匹配 {{}}
    if (dataReg.test(text)) {
      // const vnode = createVNode(nodeType, null, text, node)
      node.textContent = text.replace(dataReg, (matched, placeholder) => {
        const pathArray = []
        const keys = placeholder.trim().split('.')
        const textContent = getInstanceValue(keys, comp, (property) => {
          pathArray.push(property)
        })
        initWatcher(keys, comp, node, 'textContent', text) // 收集器初始化并收集相关node
        return textContent ? textContent : (getDataType(textContent) === 'undefined' || getDataType(textContent) === 'null' ? '' : textContent)// 当值为null或者undefined时，转化成空字符
      })
    } else { // 匹配其他文本节点，暂不操作（空白节点、空格符、换行符等）
    }
  }
  //匹配 元素节点，例如 <p> 和 <div>
  else if (nodeType === Node.ELEMENT_NODE) {
    // const vnode = createVNode(nodeType, attrs, text, node)
    for (let i = 0; i < attrs.length; i++) {
      const attr = attrs[i]
      const attrName = attr.name
      const attrValue = attr.value
      if (attrName.startsWith(':')) { // 解析动态绑定属性
        const attributeName = attrName.slice(1)
        if (attributeName === 'model') { // 匹配 :model
          node.addEventListener('input', (e) => {
            const inputVal = e.target.value
            const keys = attrValue.split('.')
            if (keys.length > 1) { // 多级引用类型
              const lastKey = keys.splice(keys.length - 1)[0];
              const targetKey = getInstanceValue(keys, comp)
              targetKey[lastKey] = inputVal
            } else { // 基础类型
              comp[keys[0]] = inputVal
            }
          })
          const val = getInstanceValue(attrValue.split('.'), comp) // 将data中对应值赋值到文本元素节点
          node.value = val ? val : '' // 当值为null或者undefined时，转化成空字符
          initWatcher(attrValue.split('.'), comp, node, 'value') // 收集器初始化并收集相关node
        } else if (attributeName === 'for') { // 匹配 :for
          node.removeAttribute(attrName)
          const array = attrValue.match(/(?<=in\s+).+/) // 匹配 in 字符后面的数组变量名
          const val = getInstanceValue(array[0].split('.'), comp) // 将data中对应值赋值到文本元素节点

          console.log(nodeName, nodeType, nodeValue, text);
        } else if (attributeName === 'key') { // 匹配 :key
        } else if (attributeName === 'if') { // 匹配 :if
          if (attrValue.split('===').length === 2 || attrValue.split('==').length === 0) { // 布尔表达式 暂不支持
            throw new LveError('lve.js提示', '暂不支持布尔表达式写法')
          } else { // 变量
            const val = getInstanceValue(attrValue.split('.'), comp) // 将data中对应值赋值到文本元素节点
            node.removeAttribute(attrName)
            let oComment = document.createComment('') // 创建空白注释节点
            if (!val) { // 初始化 :if 时操作dom
              node.parentNode.insertBefore(oComment, node);
              node.parentNode.removeChild(node)
            }
          }
        } else if (attributeName === 'show') { // 匹配 :show
          node.removeAttribute(attrName)
          const defaultDisplay = getComputedStyle(node, null)['display'] // 获取元素默认display
          const val = getInstanceValue(attrValue.split('.'), comp) // 将data中对应值获取到
          node.style['display'] = val ? defaultDisplay : 'none' // 初始化 :show 时设置dom display样式
          initWatcher(attrValue.split('.'), comp, node, 'display', defaultDisplay) // 收集器初始化并收集相关node
        } else if (attributeName === 'value') { // 匹配 :value
          node.removeAttribute(attrName)
          const attributeValue = getInstanceValue(attrValue.split('.'), comp)
          node.setAttribute(attributeName, attributeValue) // 设置节点的value属性
          i-- // 因为增加了一属性，所以索引值应该往前移一格
        } else {
          const attributeValue = getInstanceValue(attrValue.split('.'), comp)
          node.setAttribute(attributeName, attributeValue)
          initWatcher(attrValue.split('.'), comp, node, 'value') // 收集器初始化并收集相关node
          node.removeAttribute(attrName) // 绑定后必须移除掉，不然无法执行最新数据
          i-- // 因为增加了一属性，所以索引值应该往前移一格
        }
      }
      if (attrName.startsWith('@')) { // 解析@对应绑定方法
        const event = attrName.slice(1)
        const method = attrValue
        const reg = /(?<=\(*)\w+(?=\(*)/g // 匹配 xxx(xxx) ，暂时不支持 () => xxx(xxx)
        const matched = method.match(reg)
        node.addEventListener(event, (e) => { // 方法中加入变量暂时有问题
          if (matched.length === 1) {
            if (e.type === 'click') {
              comp.$methods[matched[0]].call(comp)
            } else { // 类似于input, change 都有绑定节点自身的target
              comp.$methods[matched[0]].call(comp, e)
            }
          } else {
            comp.$methods[matched[0]].call(comp, ...matched.slice(1))
          }
        })
        node.removeAttribute(attrName) // 绑定后必须移除掉，不然无法执行最新数据
      }
    }
  // 遇到其他类型的节点 都跳过
  } else {
    return
  }
}
export {
  parse
} 